package nl.utwente.ewi.hmi.multitouch.analysis.matching;

import java.awt.Dimension;
import java.awt.geom.Point2D;
import java.util.NavigableSet;

import nl.utwente.ewi.hmi.multitouch.TouchDeviceInfo;
import nl.utwente.ewi.hmi.multitouch.analysis.Segment;

public class LinearSegmentMatching extends SegmentMatching {

	protected Dimension size = null;
	
	public LinearSegmentMatching(TouchDeviceInfo touchDeviceInfo) {
		super(touchDeviceInfo);
		this.size = touchDeviceInfo.getSize();
	}

	@Override
	public double getConfidence(NavigableSet<Segment> history, Segment testSegment) {

		if(history.isEmpty()) {
			return 0d;
		}
		
		Segment segment = history.last();

		if(!(testSegment.getTangible() == segment.getTangible() || testSegment.getTangible().canJoinInto(segment.getTangible()) 
				|| testSegment.getTangible().canSplitInto(segment.getTangible()))) {
			return 0d;
		}
		
		// If an object is known to be unique by tangible, match it 100%
		if(testSegment.getTangible().isUnique()) {
			return 1d;
		}
		
		Point2D velocity = new Point2D.Float(0, 0);

		if(history.size() > 1) {
			Segment preLastSegment = history.lower(segment);
			
			Point2D origin0 = preLastSegment.getOrigin();
			Point2D origin1 = segment.getOrigin();
			
			long timeStep = segment.getTime() - preLastSegment.getTime();

			// velocity in px / s
			velocity.setLocation( ((origin1.getX() - origin0.getX()) * 1000) / timeStep
								 ,((origin1.getY() - origin0.getY()) * 1000) / timeStep);
		}


		double areaDifference = Math.abs((segment.getMass() - testSegment.getMass()) / (double) (size.width * size.height));
		
		Point2D origin = segment.getOrigin();
		
		long timeStep = testSegment.getTime() - segment.getTime();
		
		Point2D projectedOrigin = new Point2D.Float((float)origin.getX() + (float) (velocity.getX() * timeStep) / 1000
												  , (float)origin.getY() + (float) (velocity.getY() * timeStep) / 1000);

		double centroidDistance = testSegment.getOrigin().distance(projectedOrigin); 

		double maximumDistance = Math.sqrt((size.width * size.width) + (size.height * size.height)); 

		double relCentroidDistance = centroidDistance / maximumDistance;
		
		
		double confidence = 1 - (Math.sqrt((relCentroidDistance * relCentroidDistance) + (areaDifference * areaDifference)) / Math.sqrt(2));
		
		
		return confidence;
	}
	
}
